#include "ProductSpace.hpp"

ProductSpace::ProductSpace(const ElementarySpace& es) {
	subSpaces_.push_back(es);
}

ProductSpace& ProductSpace::operator*=(const ProductSpace& other) {
	for (std::list<ElementarySpace>::const_iterator i =
			other.subSpaces_.begin();
			i != other.subSpaces_.end(); ++i) {
		if (newTag(*i)) {
			subSpaces_.push_back(*i);
		} else {
			throw std::runtime_error("Duplicate subspaces in Kronecker product.");
		}
	}
	return *this;
}

int ProductSpace::dim() const {
	int d = 1;
	for (std::list<ElementarySpace>::const_iterator i =
			subSpaces_.begin(); i != subSpaces_.end(); ++i) {
		d *= i->dim();
	}
	return d;
}

void ProductSpace::print() const {
	for (std::list<ElementarySpace>::const_iterator i =
			subSpaces_.begin();
			i != subSpaces_.end(); ++i) {
		std::cout << "(" << i->getName() << ":" <<
			i->dim() << ")";
	}
	std::cout << std::endl;
}

bool ProductSpace::newTag(const ElementarySpace& es) {
	bool isNew = true;
	for (std::list<ElementarySpace>::const_iterator i =
			subSpaces_.begin(); i != subSpaces_.end(); ++i) {
		if (es.getName() == i->getName()) {
			isNew = false;
		}
	}
	return isNew;
}

ProductSpace tensorProduct(const ProductSpace& h1, const ProductSpace& h2) {
	ProductSpace temp(h1);
	for (std::list<ElementarySpace>::const_iterator i = h2.subSpaces().begin();
			i != h2.subSpaces().end(); ++i) {
		temp *= *i;
	}
	return temp;
}

